package com.xlh.openai.service.impl;


import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.plexpt.chatgpt.entity.chat.Message;
import com.unfbx.chatgpt.entity.chat.ChatChoice;
import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse;
import com.xlh.openai.dto.ChatCompletionResponseWapperDTO;
import com.xlh.openai.entity.ChatRecordsEntity;
import com.xlh.openai.entity.TopicsEntity;
import com.xlh.openai.entity.WechatUserEntity;
import com.xlh.openai.exception.ServiceException;
import com.xlh.openai.service.*;
import com.xlh.openai.utils.JsonUtils;
import com.xlh.openai.utils.QrcodeUtils;
import com.xlh.openai.utils.RequestUtil;
import com.xlh.openai.vo.ConversationListVO;
import com.xlh.openai.vo.UserInfoVO;
import com.xlh.openai.vo.WechatQRcodeVO;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.UUID;


@Service("webChatService")
@Slf4j
public class WebChatServiceImpl implements WebChatService {

    @Autowired
    private WxMpService wxMpService;

    @Autowired
    private WechatUserService wechatUserService;

    @Autowired
    private ChatRecordsService chatRecordsService;

    @Autowired
    private AIService aIService;

    @Autowired
    private HttpSession session;

    @Autowired
    private TopicsService topicsService;

    @Autowired
    private HttpServletRequest request;

    @Value("${knife4j.production}")
    private Boolean production;

    /**
     * 二维码缓存五分钟
     */
    private static Cache<String,String> sceneIdMap = CacheUtil.newTimedCache(300 * 1000);


    public static void putSceneIdMap( String sceneId, String openId ){
        sceneIdMap.put(sceneId, openId);
    }

    @Override
    public WechatQRcodeVO getQRcode(HttpSession session) {

        // 场景ID
        String sceneId = session.getId();
        sceneIdMap.put(sceneId, "");
        WechatQRcodeVO wechatQRcodeVO = new WechatQRcodeVO();
        try {
            WxMpQrCodeTicket wxMpQrCodeTicket = wxMpService.getQrcodeService().qrCodeCreateTmpTicket(sceneId, 300);
            String url = wxMpQrCodeTicket.getUrl();
            QrcodeUtils.getQrCode(url).toFile("D:\\software\\nginx\\dxx\\image\\" + FileUtil.getName(url)+".png");
            String visitUrl = "http://localhost:30400/image/" + FileUtil.getName(url) +".png";
            wechatQRcodeVO.setSceneId(sceneId);
            wechatQRcodeVO.setQrcodeUrl(visitUrl);

        } catch (WxErrorException | IOException e) {
            throw new ServiceException(" 生成二维码异常！");
        }

        return wechatQRcodeVO;
    }

    @Override
    public UserInfoVO wechatIsLogin(HttpSession session, String sceneId) {

        WechatUserEntity userEntity = wechatUserService.getLoginUserInfo(session);
        if(userEntity == null){
            String openId = sceneIdMap.get(sceneId);
            if(StrUtil.isNotBlank(openId)){
                userEntity = wechatUserService.getByOpenId(openId);
            }
        }

        UserInfoVO userInfoVO = new UserInfoVO();
        // 封装成功
        if( userEntity == null ){
            userInfoVO.setIsSuccessLogin(false);
            userInfoVO.setPhone("15910470044");
            userInfoVO.setUserName("朱允炆");
            return userInfoVO;
        }else{
            userInfoVO.setIsSuccessLogin(true);
            userInfoVO.setPhone("15910470044");
            userInfoVO.setUserName("朱允炆");

            // 从缓存中删除场景ID
            session.setAttribute("id", userEntity );
            sceneIdMap.remove(sceneId);
            return userInfoVO;
        }
    }

    @Override
    public SseEmitter chatStreamQuestion( String prompt,
                                          String parentMessageId,
                                          String conversationId,
                                          Integer topicId )  {
        // 非生产环境使用测试账号
        if(production == false){
            session.setAttribute(WechatUserServiceImpl.SESSION_OPENID_KEY, "o_uia6LmmJ_6XHIQxMskwaketkmk");
        }
        String answers = "您当前的问答次数已用尽，请购买次数后再使用！";
        // 查询当前用户剩余次数
        SseEmitter sseEmitter = new SseEmitter();
        WechatUserEntity userEntity = wechatUserService.getLoginUserInfo(session);
        String ipAddress = RequestUtil.getIpAddress(request);
        log.info( "------ current user ip: ------" + ipAddress);
        List<Message> messages = chatRecordsService.listMessages(userEntity.getId(), conversationId);

        if(ObjectUtil.isNotNull(topicId)){

            TopicsEntity topicsEntity = topicsService.getById(topicId);
            if(ObjectUtil.isNull(topicsEntity)){
                log.error(" not found topicId in db : " + topicId);
                throw new ServiceException(" not found topicId in db ");
            }
            ChatRecordsEntity chatRecordsEntity = new ChatRecordsEntity();
            chatRecordsEntity.setQuestion(topicsEntity.getTopicDescription());
            chatRecordsEntity.setUserId(userEntity.getId());
            chatRecordsEntity.setAnswer(topicsEntity.getTopicResponse());
            chatRecordsEntity.setConversationId(conversationId);
            chatRecordsEntity.setSendTime(new Date());
            chatRecordsService.save(chatRecordsEntity);
            otherHandler(parentMessageId, conversationId, sseEmitter, topicsEntity.getTopicResponse());
            return sseEmitter;
        }

        if(userEntity.getQuestionTime() > 0){
            try {
                // 获取当前的聊天记录
                sseEmitter = aIService.chatStreamQuestion( userEntity.getId(), prompt, parentMessageId, messages, conversationId);
                // 公司地址
                if(ipAddress.equals("112.103.254.249") == false){
                    wechatUserService.consumeTime(userEntity);
                }
            } catch (Exception e) {
                e.printStackTrace();
                answers = "小码正在努力为您解析！";
                otherHandler(parentMessageId, conversationId, sseEmitter, answers);
            }
        }else{
            otherHandler(parentMessageId, conversationId, sseEmitter, answers);
        }
        return sseEmitter;
    }

    /**
     * 处理非正常调用chatGpt的请求
     * @param parentMessageId
     * @param conversationId
     * @param sseEmitter
     * @param answers
     */
    private void otherHandler( String parentMessageId, String conversationId, SseEmitter sseEmitter, String answers ) {

        ChatCompletionResponseWapperDTO chatCompletionDTO = new ChatCompletionResponseWapperDTO();
        chatCompletionDTO.setId(UUID.randomUUID().toString());
        chatCompletionDTO.setParentMessageId(parentMessageId);
        chatCompletionDTO.setText(answers);
        chatCompletionDTO.setConversationId(conversationId);

        ChatCompletionResponse chatCompletionResponse = new ChatCompletionResponse();
        chatCompletionResponse.setId("-1");
        chatCompletionResponse.setModel("gpt-3.5-turbo-0301");
        chatCompletionResponse.setCreated(-1L);
        chatCompletionResponse.setObject("chat.completion.chunk");

        ChatChoice chatChoice = new ChatChoice();
        chatChoice.setIndex(0);
        com.unfbx.chatgpt.entity.chat.Message delta = new com.unfbx.chatgpt.entity.chat.Message();
        delta.setContent("");
        chatChoice.setDelta(delta);
        chatChoice.setFinishReason("stop");
        chatCompletionResponse.setChoices(Lists.newArrayList(chatChoice));

        chatCompletionDTO.setChatCompletionResponse(chatCompletionResponse);
        String responseJson = JsonUtils.toJson(chatCompletionDTO);
        SseEventBuilderImpl sseEventBuilderImpl = new SseEventBuilderImpl();
        sseEventBuilderImpl.data(responseJson, MediaType.APPLICATION_OCTET_STREAM);
        try {
            sseEmitter.send(sseEventBuilderImpl);
        } catch (IOException e) {
            log.error("发送信息异常");
            e.printStackTrace();
            sseEmitter.complete();
        }
        sseEmitter.complete();
    }


    @Override
    public List<ConversationListVO> conversationList() {

        getCurrentUser();
        return null;
    }

    @Override
    public WechatUserEntity getCurrentUser(){
        Object id = session.getAttribute("id");
        if(id == null){
            throw new ServiceException("当前用户未登录！");
        }else{
            Integer userId =  (Integer) id;
            WechatUserEntity wechatUser = wechatUserService.getById(userId);
            return wechatUser;
        }
    }

    @Override
    public SseEmitter testChatStreamQuestion( String prompt,
                                          String parentMessageId,
                                          String conversationId,
                                          Integer topicId )  {

        session.setAttribute(WechatUserServiceImpl.SESSION_OPENID_KEY, "o_uia6LmmJ_6XHIQxMskwaketkmk");
        String answers = "您当前的问答次数已用尽，请购买次数后再使用！";
        // 查询当前用户剩余次数
        SseEmitter sseEmitter = new SseEmitter();
        WechatUserEntity userEntity = wechatUserService.getLoginUserInfo(session);
        String ipAddress = RequestUtil.getIpAddress(request);
        log.info( "------ current user ip: ------" + ipAddress);
        List<Message> messages = chatRecordsService.listMessagesTest(userEntity.getId(), conversationId);

        if(ObjectUtil.isNotNull(topicId)){

            TopicsEntity topicsEntity = topicsService.getById(topicId);
            if(ObjectUtil.isNull(topicsEntity)){
                log.error(" not found topicId in db : " + topicId);
                throw new ServiceException(" not found topicId in db ");
            }
            ChatRecordsEntity chatRecordsEntity = new ChatRecordsEntity();
            chatRecordsEntity.setQuestion(topicsEntity.getTopicDescription());
            chatRecordsEntity.setUserId(userEntity.getId());
            chatRecordsEntity.setAnswer(topicsEntity.getTopicResponse());
            chatRecordsEntity.setConversationId(conversationId);
            chatRecordsEntity.setSendTime(new Date());
            chatRecordsService.save(chatRecordsEntity);
            otherHandler(parentMessageId, conversationId, sseEmitter, topicsEntity.getTopicResponse());
            return sseEmitter;
        }

        if(userEntity.getQuestionTime() > 0){
            try {
                // 获取当前的聊天记录
                sseEmitter = aIService.chatStreamQuestion( userEntity.getId(), prompt, parentMessageId, messages, conversationId);
                // 公司地址
                if(ipAddress.equals("112.103.254.249") == false){
                    wechatUserService.consumeTime(userEntity);
                }
            } catch (Exception e) {
                e.printStackTrace();
                answers = "小码正在努力为您解析！";
                otherHandler(parentMessageId, conversationId, sseEmitter, answers);
            }
        }else{
            otherHandler(parentMessageId, conversationId, sseEmitter, answers);
        }
        return sseEmitter;
    }


}
